package com.web.main.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.entity.Pile;
import com.common.entity.Site;
import com.common.entity.Supplier;
import com.web.main.entity.form.SiteForm;
import com.web.main.entity.param.SiteQuery;
import com.web.main.entity.vo.PileVo;
import com.web.main.entity.vo.SiteVo;
import com.web.main.entity.vo.SupplierVo;
import com.web.main.exception.SiteException;
import com.web.main.mapper.PileMapper;
import com.web.main.mapper.SiteMapper;
import com.web.main.mapper.SupplierMapper;
import com.web.main.service.SiteService;
import com.web.main.utils.DistanceUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 长顺
 * @since 2020-11-26
 */
@Service
public class SiteServiceImpl extends ServiceImpl<SiteMapper, Site> implements SiteService {
    @Autowired
    PileMapper pileMapper;

    @Autowired
    SupplierMapper supplierMapper;

    /**
     * 添加电站
     * @param siteForm
     */
    @Override
    public void addSite(SiteForm siteForm) {
        if(siteForm == null) {
            throw new SiteException("site is null");
        }
        Site site = new Site();
        BeanUtils.copyProperties(siteForm, site);
        site.setSiteId(null);  //删除主键
        site.setSiteState(null);  //删除状态
        int insert = baseMapper.insert(site);
        if(insert == 0) {
            throw new SiteException("add site fail");
        }
    }

    /**
     * 根据电站id删除电站
     * @param siteId
     */
    @CacheEvict(value = "siteVo", allEntries = true)
    @Override
    public void removeSiteById(String siteId) {
        if(StringUtils.isBlank(siteId)) {
            throw new SiteException("remove site fail with id is null");
        }
        //先查询，在修改.
        Site site = selectEqIdNeState(siteId);
        //再修改
        site.setSiteState(-1);
        int i = baseMapper.updateById(site);
        if(i == 0) {
            throw new SiteException("remove site fail with id :" + siteId);
        }
    }

    /**
     * 修改电站信息
     * @param siteForm
     */
    @CacheEvict(value = "siteVo", allEntries = true)
    @Override
    public void modifySite(SiteForm siteForm) {
        if(ObjectUtils.isEmpty(siteForm)) {
            throw new SiteException("param is null");
        }

        //先查询，再修改。已经非空判断
        Site site = selectEqIdNeState(siteForm.getSiteId());

        String siteName = siteForm.getSiteName();
        String siteAddress = siteForm.getSiteAddress();
        String sitePiePhoto = siteForm.getSitePiePhoto();
        String siteStallPhoto = siteForm.getSiteStallPhoto();
        String sitePanoramaPhoto = siteForm.getSitePanoramaPhoto();
        String siteLongitude = siteForm.getSiteLongitude();
        String siteDimensionality = siteForm.getSiteDimensionality();
        Integer sitePlace = siteForm.getSitePlace();
        Integer siteAllday = siteForm.getSiteAllday();
        String siteRemark = siteForm.getSiteRemark();
        Integer siteState = siteForm.getSiteState();

        if(!ObjectUtils.isEmpty(siteName)) {
            site.setSiteName(siteName);
        }
        if(!ObjectUtils.isEmpty(siteAddress)) {
            site.setSiteAddress(siteAddress);
        }
        if(!ObjectUtils.isEmpty(sitePiePhoto)) {
            site.setSitePiePhoto(sitePiePhoto);
        }
        if(!ObjectUtils.isEmpty(siteStallPhoto)) {
            site.setSiteStallPhoto(siteStallPhoto);
        }
        if(!ObjectUtils.isEmpty(sitePanoramaPhoto)) {
            site.setSitePanoramaPhoto(sitePanoramaPhoto);
        }
        if(!ObjectUtils.isEmpty(siteLongitude)) {
            site.setSiteLongitude(siteLongitude);
        }
        if(!ObjectUtils.isEmpty(siteDimensionality)) {
            site.setSiteDimensionality(siteDimensionality);
        }
        if(!ObjectUtils.isEmpty(sitePlace)) {
            site.setSitePlace(sitePlace);
        }
        if(!ObjectUtils.isEmpty(siteAllday)) {
            site.setSiteAllday(siteAllday);
        }
        if(!ObjectUtils.isEmpty(siteRemark)) {
            site.setSiteRemark(siteRemark);
        }
        if(!ObjectUtils.isEmpty(siteState)) {
            site.setSiteState(siteState);
        }
        //在修改
        int i = baseMapper.updateById(site);
        if(i == 0) {
            throw new SiteException("modify fail");
        }
    }

    /**
     * 查询所有的电站
     * @return
     */
    @Cacheable(value = "siteVo", key = "'getAllSite'")
    @Override
    public List<SiteVo> getAllSite() {
        QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("site_state", 1);  //可以使用的。-1删除，0待审
        List<Site> sites = baseMapper.selectList(queryWrapper);
        //1.属性拷贝
        List<SiteVo> siteVos = copyPropertiesList(sites);  //自己写的

        for (int i = 0; i < siteVos.size(); i++) {
            SiteVo siteVo = siteVos.get(i);
            //2.给前端电站对象补全电站和供应商信息。
            siteVoAssignment(siteVo, null);
        }
        return siteVos;
    }

    /**
     * 查看一个
     * @param siteId
     * @return
     */
    @Cacheable(value = "siteVo", key = "#p0")
    @Override
    public SiteVo getOneSiteById(String siteId) {
        //查
        Site site = selectEqIdNeState(siteId);
        //1.属性值拷贝
        SiteVo siteVo = new SiteVo();
        BeanUtils.copyProperties(site, siteVo);
        //2.给前端电站对象补全电站和供应商信息。
        siteVoAssignment(siteVo, null);
        return siteVo;
    }

    /**
     * 查看当前省份的所有电站。地图
     * @param city 省
     * @return
     */
    @Cacheable(value = "siteVo", key = "#p0")
    @Override
    public List<SiteVo> getThisProvinceAllSite(String city) {
        //需要验证传过来的数据是不是省份/直辖市/自治区
        if(StringUtils.isBlank(city)) {
            throw new SiteException("select fail with city is null");
        }
        QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("site_state", 1);  //可以使用的。-1删除，0待审。
        queryWrapper.like("site_address", city);
        List<Site> sites = baseMapper.selectList(queryWrapper);
        if(ObjectUtils.isEmpty(sites)) {
            throw new SiteException("select fail with province:" + city);
        }
        //属性拷贝
        List<SiteVo> siteVos = copyPropertiesList(sites);  //自己写的

        //属性填充
        for (int i = 0; i < siteVos.size(); i++) {
            siteVoAssignment(siteVos.get(i), null);
        }
        return siteVos;
    }

    /**
     * 分页+条件查看附近的电桩
     * @param siteQuery
     * @return
     */
//    @Cacheable(value = "siteQuery", key = "#siteQuery.page")
    @Override
    public Page<SiteVo> pageQuery(SiteQuery siteQuery) {
        Integer page = siteQuery.getPage();
        Integer limit = siteQuery.getLimit();
        Page<Site> sitePage = new Page<>(page, limit);
        QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
        //查可以使用的。
        queryWrapper.eq("site_state", 1);  //可以使用的。-1删除，0待审

        if(!ObjectUtils.isEmpty(sitePage)) {  //条件对象不为空
            //其他筛选条件
            String siteName = siteQuery.getSiteName();  //电站表
            Integer sitePlace = siteQuery.getSitePlace();
            Integer siteAllday = siteQuery.getSiteAllday();
            if(!ObjectUtils.isEmpty(siteName)) {  //站点名字
                queryWrapper.like("site_name", siteName);
            }
            if(!ObjectUtils.isEmpty(sitePlace)) {
                queryWrapper.eq("site_place", sitePlace);
            }
            if(!ObjectUtils.isEmpty(siteAllday)) {
                queryWrapper.eq("site_allday", siteAllday);
            }
        }

        //分页查
        baseMapper.selectPage(sitePage, queryWrapper);

        //资源拷贝
        Page<SiteVo> siteVoPage = new Page<>(page, limit);
        BeanUtils.copyProperties(sitePage, siteVoPage);
        //需要重新赋值当前页信息
        List<SiteVo> pileVos = new ArrayList<>();
        for (int i = 0; i < sitePage.getRecords().size(); i++) {
            Site site = sitePage.getRecords().get(i);
            SiteVo siteVo = new SiteVo();
            BeanUtils.copyProperties(site, siteVo);
            pileVos.add(siteVo);
        }
        siteVoPage.setRecords(pileVos);
        //填充电桩对象和供应商对象
        List<SiteVo> records = siteVoPage.getRecords();
        for (int i = 0; i < records.size(); i++) {
            SiteVo siteVo = records.get(i);
            siteVoAssignment(siteVo, siteQuery);
        }

        //获取条件距离和用户经纬度
//        Integer distance = siteQuery.getDistance();  //距离
//        String longitude = siteQuery.getLongitude();  //经度
//        String dimension = siteQuery.getDimension();  //纬度
//
//        //筛选不在规定距离中的对象
//        filter(distance, sitePage, longitude, dimension);

        return siteVoPage;
    }

    /**
     * 获取所有待审批的电站
     * @return
     */
//    @Cacheable(value = "site", key = "'getPendingSite'")
    @Override
    public List<SiteVo> getPendingSite() {
        QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("site_state", 0);
        List<Site> sites = baseMapper.selectList(queryWrapper);
        if(ObjectUtils.isEmpty(sites)) {
            return null;
//            throw new SiteException("does not have pending site");
        }
        //集合的属性拷贝
        List<SiteVo> siteVos = copyPropertiesList(sites);
        //填充对象和供应商信息。
        for (int i = 0; i < siteVos.size(); i++) {
            SiteVo siteVo = siteVos.get(i);
            siteVoAssignment(siteVo, null);
        }
        return siteVos;
    }

    /**
     * 给前端电站对象补全电桩和供应商信息
     * @param siteVo
     */
    private void siteVoAssignment(SiteVo siteVo, SiteQuery siteQuery) {
        //1.用电站的id查电桩表
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("site_id", siteVo.getSiteId());
        queryWrapper.ne("pile_state", -1);
        if(!ObjectUtils.isEmpty(siteQuery)) {
            Integer pileModel = siteQuery.getPileModel();  //电桩表
            Integer pileType = siteQuery.getPileType();  //电桩表
            if(!ObjectUtils.isEmpty(pileType)) {
                queryWrapper.eq("pile_type", pileType);
            }
            if(!ObjectUtils.isEmpty(pileModel)) {
                queryWrapper.eq("pile_model", pileModel);
            }
        }
        List<Pile> piles = pileMapper.selectList(queryWrapper);
        if(ObjectUtils.isEmpty(piles)) {
            return;
//            throw new SiteException("select site fail");
        }
        //2.属性拷贝
        List<PileVo> pileVos = new ArrayList<>();
        for (int i = 0; i < piles.size(); i++) {
            PileVo pileVo = new PileVo();
            BeanUtils.copyProperties(piles.get(i),pileVo);
            pileVos.add(pileVo);
        }
        //填充
        for (int j = 0; j < pileVos.size(); j++) {
            PileVo pileVo = pileVos.get(j);
            //3.用供应商条件查
            QueryWrapper<Supplier> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("supplier_id", pileVo.getSupplierId());
            if(!ObjectUtils.isEmpty(siteQuery)) {
                String supplierName = siteQuery.getSupplierName();  //供应商表
                if(!ObjectUtils.isEmpty(supplierName)) {  //供应商名
                    queryWrapper1.like("supplier_name", supplierName);
                }
            }
            Supplier supplier = supplierMapper.selectOne(queryWrapper1);
            if(ObjectUtils.isEmpty(supplier)) {
                return;
//                throw new SiteException("select site fail");
            }
            //4.属性拷贝
            SupplierVo supplierVo = new SupplierVo();
            BeanUtils.copyProperties(supplier, supplierVo);
            //5.将供应商赋值给电桩
            pileVo.setSupplierVo(supplierVo);
        }
        //6.将电桩赋值给电站
        siteVo.setPileVos(pileVos);
    }

    /**
     * 根据经纬度筛选
     * @param siteCoPage  距离
     * @param distance  分页对象
     * @param longitude  用户经度
     * @param dimension  用户纬度
     * @return
     */
    private void filter(Integer distance, Page<SiteVo> siteCoPage, String longitude, String dimension) {
        List<SiteVo> records = siteCoPage.getRecords();  //获取当前页数据
        Iterator<SiteVo> iterator = records.iterator();
        while(iterator.hasNext()) {
            SiteVo siteVo = iterator.next();
            String siteLongitude = siteVo.getSiteLongitude();  //获取经度
            String siteDimensionality = siteVo.getSiteDimensionality();  //获取纬度
            //判断是否符合要求
            boolean flag = DistanceUtil.isWithin(distance, longitude.toString(), dimension.toString(),
                    siteLongitude.toString(), siteDimensionality.toString());
            if(!flag) {  //这个经纬度不在指定范围内，删除
                iterator.remove();
            }
        }
    }

    /**
     * 抽取方法，根据主键查询状态不为-1的。
     * @param siteId
     * @return
     */
    private Site selectEqIdNeState(String siteId) {
        QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("site_id", siteId);
        queryWrapper.ne("site_state", -1);
        Site site = baseMapper.selectOne(queryWrapper);
        if(ObjectUtils.isEmpty(site)) {
            throw new SiteException("site does not exits");
        }
        return site;
    }

    /**
     * 属性拷贝。拷贝集合。
     * @param sites
     * @return
     */
    private List<SiteVo> copyPropertiesList(List<Site> sites) {
        List<SiteVo> siteVos = new ArrayList<>();
        for (int i = 0; i < sites.size(); i++) {
            SiteVo siteVo = new SiteVo();
            BeanUtils.copyProperties(sites.get(i), siteVo);
            siteVos.add(siteVo);
        }
        return siteVos;
    }

}
